home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk1 / semaphorestutor / msgsem.c < prev    next >
C/C++ Source or Header  |  1995-03-18  |  3KB  |  168 lines

  1. #include <exec/types.h>
  2. #include <exec/nodes.h>
  3. #include <exec/ports.h>
  4. #include <exec/semaphores.h>
  5. #include <exec/memory.h>
  6.  
  7. struct MsgPort *CreatePort();
  8. struct MsgPort *FindPort();
  9. struct XSemaphore *CreateSemaphore();
  10. void DeleteSemaphore();
  11. void *AllocMem();
  12. void cleanup();
  13.  
  14. struct XSemaphore {
  15.     struct Semaphore s;
  16.     WORD Users;
  17. };
  18.  
  19. struct MsgPort *port = 0;
  20. struct XSemaphore *sem = 0;
  21. struct Message msg;
  22.  
  23. /* I made this extended semaphore so that there is an easy way to
  24.  * keep track of when it is safe to delete it.  If anyone can think
  25.  * of a better way to do this, I'd love to hear it.
  26.  */
  27.  
  28. extern int Enable_Abort;
  29.  
  30. main()
  31. {
  32.     int i;
  33.     Enable_Abort = 0;
  34.  
  35.     /* the existance check/creation must be atomic --> Forbid/Permit */
  36.     Forbid();
  37.     if (!(sem = (struct XSemaphore *)FindPort("my semaphore")))
  38.         sem = CreateSemaphore("my semaphore", 0);
  39.     else
  40.         sem->Users++;
  41.  
  42.     Permit();
  43.  
  44.     if (!sem) {
  45.         printf("Error, can't find *or* create semaphore\n");
  46.         cleanup();
  47.         exit(100);
  48.     }
  49.  
  50.     port = CreatePort(0,0);
  51.     if (!port) {
  52.         printf("Error, can't create my reply port\n");
  53.         cleanup();
  54.     }
  55.  
  56.     msg.mn_Node.ln_Type = NT_MESSAGE;
  57.     msg.mn_Length        = sizeof(struct Message);
  58.     msg.mn_ReplyPort    = port;
  59.  
  60.     /* for P & V fans, the Procure & Vacate names are mnemonic */
  61.     /*               -         -                   */
  62.  
  63.     for (i=0;i<5;i++) {
  64.         if (!Procure(sem, &msg)) {
  65.             WaitPort(port);    /* wait for the message to come */
  66.             GetMsg(port);    /* get it */
  67.         }
  68.  
  69.         /* we now have exclusive access */
  70.  
  71.         printf("\nTask $%06x owns the semaphore\n",FindTask(0));
  72.  
  73.         /* pretend to so some action requiring semaphore */
  74.         Delay(1 + (rand()&31));
  75.  
  76.         printf("\t\t...semaphore now released\n");
  77.  
  78.         /* yield control to someone else */
  79.         Vacate(sem);
  80.  
  81.         /* pretend to so some action not requiring semaphore */
  82.         Delay(1 + (rand()&31));
  83.  
  84.     }
  85.  
  86.     cleanup();
  87.  
  88. }
  89.  
  90. void cleanup()
  91. {
  92.     if (port) {
  93.         DeletePort(port);
  94.         port = 0;
  95.     }
  96.  
  97.     /*
  98.      * we'd like to use the semaphore to lock out other users here 
  99.      * but we'd have to somehow P and then not do a V but delete
  100.      * the port instead for this to work... That hurts me more than
  101.      * the Forbid() Permit() pair...
  102.      */
  103.  
  104.     if (sem) {
  105.         /* the user check/delete must be atomic --> Forbid/Permit */
  106.  
  107.         Forbid();
  108.         if (--sem->Users == 0)
  109.             DeleteSemaphore(sem);
  110.         Permit();
  111.  
  112.         sem = 0;
  113.     }
  114. }
  115.  
  116. struct XSemaphore *CreateSemaphore(name,pri)
  117. char *name;
  118. int pri;
  119. {
  120.     struct XSemaphore *s;
  121.     char *buf;
  122.  
  123.     s = AllocMem(sizeof(struct XSemaphore), MEMF_PUBLIC|MEMF_CLEAR);
  124.     if (!s)
  125.         return(0);
  126.  
  127.     s->s.sm_Bids = -1;
  128.     NewList(&s->s.sm_MsgPort.mp_MsgList);
  129.     s->s.sm_MsgPort.mp_Flags    = PA_IGNORE;
  130.     s->s.sm_MsgPort.mp_Node.ln_Type    = NT_SEMAPHORE;
  131.     s->s.sm_MsgPort.mp_Node.ln_Pri    = pri;
  132.     s->Users            = 1;
  133.  
  134.     /* Note that the name must be copied as the original creator
  135.      * of the semaphore might exit.  We can't leave a pointer to
  136.      * the original data segment lying around after the program
  137.      * has exited.  
  138.      */
  139.     if (name) {
  140.         buf = AllocMem(strlen(name)+1, MEMF_PUBLIC);
  141.         if (!buf) {
  142.             FreeMem(s, sizeof(struct XSemaphore));
  143.             return(0);
  144.         }
  145.         strcpy(buf,name);
  146.         s->s.sm_MsgPort.mp_Node.ln_Name = buf;
  147.         AddPort(s);    
  148.     }
  149.     return(s);
  150. }
  151.  
  152. void DeleteSemaphore(s)
  153. struct XSemaphore *s;
  154. {
  155.     char *name;
  156.  
  157.     if (!s) return;
  158.  
  159.     name =  s->s.sm_MsgPort.mp_Node.ln_Name;
  160.  
  161.     if (name) {
  162.         RemPort(s);    /* remove from list of public semaphores */
  163.         FreeMem(name,strlen(name)+1);
  164.     }
  165.  
  166.     FreeMem(s, sizeof(struct XSemaphore));
  167. }
  168.